#include <iostream>
#include "igslib_iutil.h"
#include "igslib_idispenser.h"

namespace igslib
{
    namespace dispenser_sample
    {
        /*!
         * This sample demostrates manipulating the dispenser.
         */
        static void dispense()
        {
            ISerialManager* srm = GetSerialManagerInstance();
            ISpi* spi = srm->New_ProjMCU_spi("DragonBallRace");	
            spi->SetWorkingFrequency(10000000);

			IGPIOManager* gpm = GetGPIOManagerInstance();
            IGPIO* gpin = gpm->New_ProjMCU("DragonBallRace");
            gpin->SetSPI(spi);
            gpin->SetMode(IGPIO::mode::input);
            gpin->SetNumber(7);

            IGPIO* gpout = gpm->New_ProjMCU("DragonBallRace");
            gpout->SetSPI(spi);
            gpout->SetMode(IGPIO::mode::output);
            gpout->SetNumber(4);

            IDispenserManager* dism = GetDispenserManagerInstance();
            IDispenser* ticket = dism->New_ProjMCU("DragonBallRace");
            ticket->SetSPI(spi);
            ticket->SetConfirmRange(15,100);
            ticket->SetEmptyTime(1000);
            ticket->SetJammedTime(1000);
            ticket->SetHighActive(false);
            ticket->SetGPIO(gpin,gpout,NULL);	

            int phase = 0;
            auto lv = ticket->GetValue();
            auto ls = ticket->GetState();
            util::Log("%s> Press 'enter' to start dispense.\n",__func__);
            while(true)
            {
                auto kh = util::KbHit();
                if (kh == 27) // 'esc'
                {
                    break;
                }
                if (phase == 0)
                {
                    if (kh == 10) // enter
                    {
                        ticket->AddValue(5);
                        ticket->PrizeOut();
                        ++phase;
                    }
                }
                else if (phase == 1)
                {
                    bool update = false;
                    auto ns = ticket->GetState();
                    if (ns != ls) update = true;
                    auto nv = ticket->GetValue();
                    if (nv != lv) update = true;

                    if (update)
                    {
                        util::Log("%s> now value=%g, state=%d",__func__,nv,ns);
                    }
                    ls = ns;
                    lv = nv;

                    //if (ns == IDispenser::State::idle) phase = 0;
                    if (ns == IDispenser::State::error) phase = 0;
                    if (nv == 0) phase = 0;
                }
                spi->Update();
                util::SleepMSTime(16);
            }
            exit(EXIT_SUCCESS);
        }
    };
};
